package cy.mybatis.genui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

/**
 *
 * @author cangyan
 */
public class MainFrame extends JFrame{
    private TextField tfDriverPath;
    private TextField tfDistSrcPath;
    private TextField tfDriverClass;
    private TextField tfUserName;
    private TextField tfPassword;
    private TextField tfModelPack;
    private TextField tfMapPack;
    private TextField tfDaoPack;
    private TextField tfConnURL;
    private TextField tfQuerySql;
    private JComboBox cbbDialect;
    private JCheckBox cbCountByExample;
    private JCheckBox cbUpdateByExample;
    private JCheckBox cbDeleteByExample;
    private JCheckBox cbSelectByExample;
    private JCheckBox cbExampleQueryId;
    private JCheckBox cbOverwrite;
    private JLabel progressBar;
    private CheckTable table;
    public boolean progress = true;

    private JFrame frame;
    public MainFrame(){
        super();
        this.setSize(830, 430);
        this.setResizable(false);
        setLocationRelativeTo(getOwner());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setTitle("Mybatis代码生成器1.0");
        initUI();
        
    }
    
    private void initUI(){
        frame = this;
        JPanel mainPanel = new JPanel();
        
        BoxLayout layout = new BoxLayout(mainPanel,BoxLayout.Y_AXIS);
        mainPanel.setLayout(layout);
        mainPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
        mainPanel.add(getDriverPanel());
        mainPanel.add(getDistSrcPanel());
        mainPanel.add(getDialectPanel());
        mainPanel.add(getConnectionURLPanel());
        mainPanel.add(getQuerySqlPanel());
        mainPanel.add(getUserInfoPanel());
        mainPanel.add(getSqlMapPanel());
        mainPanel.add(getModelPackPanel());
        mainPanel.add(getDaoPackPanel());
        mainPanel.add(getByExamplePanel1());
        mainPanel.add(getByExamplePanel2());
        mainPanel.add(getBtnPanel());
        //mainPanel.setPreferredSize(new Dimension(580, mainPanel.getHeight()));
        this.add(mainPanel,BorderLayout.CENTER);
        this.add(getTablePanel(),BorderLayout.EAST);
                
        //this.add(getCopyRightPanel(),BorderLayout.PAGE_END);
        
    }
    
    public JPanel newPanel(int h){
        JPanel panel = new JPanel();
        BoxLayout layout = new BoxLayout(panel,BoxLayout.X_AXIS);
        panel.setLayout(layout);
        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
        panel.add(Box.createRigidArea(new Dimension (0,h)));
        return panel;
    }
    
    public TextField newTextField(int w,int h){
        TextField tf = new TextField();
        tf.setMaximumSize(new Dimension(w,h));
        tf.setPreferredSize(new Dimension(w,h));
        return tf;
    }
    
    public JPanel getDriverPanel(){
        JPanel driverPanel = new JPanel();
        BoxLayout layout = new BoxLayout(driverPanel,BoxLayout.X_AXIS);
        driverPanel.setLayout(layout);
        driverPanel.add(new JLabel(" 数据库驱动路径："));
        tfDriverPath = new TextField();
        JButton btn = new JButton("选择文件");
        tfDriverPath.setMaximumSize(new Dimension(390,25));
        driverPanel.add(Box.createRigidArea(new Dimension (0,35)));
        driverPanel.add(tfDriverPath);
        driverPanel.add(btn);
        
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser=new JFileChooser();
                FileNameExtensionFilter filter = new FileNameExtensionFilter(".jar", "jar");
                chooser.setFileFilter(filter);
                chooser.showOpenDialog(frame);
                if(chooser.getSelectedFile()!=null){
                    tfDriverPath.setText(chooser.getSelectedFile().getPath());
                }
                cbbDialect.updateUI();
            }
        });
        
        driverPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        return driverPanel;
    }
    
    public JPanel getDistSrcPanel(){
        JPanel panel = new JPanel();
        BoxLayout layout = new BoxLayout(panel,BoxLayout.X_AXIS);
        panel.setLayout(layout);
        panel.add(new JLabel(" 源代码保存路径："));
        tfDistSrcPath = new TextField();
        JButton btn = new JButton("选择目录");
        tfDistSrcPath.setMaximumSize(new Dimension(390,25));
        //panel.add(Box.createRigidArea(new Dimension (0,35)));
        panel.add(tfDistSrcPath);
        panel.add(btn);
        
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser=new JFileChooser();
                chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                chooser.showOpenDialog(frame);
                if(chooser.getSelectedFile()!=null){
                    tfDistSrcPath.setText(chooser.getSelectedFile().getPath());
                }
                cbbDialect.updateUI();
            }
        });
        
        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
        return panel;
    }
    
    public JPanel getCopyRightPanel(){
        JPanel copyRightPanel = new JPanel();
        FlowLayout flowLayout = new FlowLayout(FlowLayout.RIGHT);
        JLabel copyRight = new JLabel("Email:beetle082@163.com @藏言");
        copyRight.setFont(new Font(copyRight.getFont().getName(), copyRight.getFont().getStyle(), 13));
        copyRightPanel.setLayout(flowLayout);
        copyRightPanel.add(copyRight);
        return copyRightPanel;
    }
    
    public JPanel getUserInfoPanel(){
        JPanel panel = newPanel(32);
        tfUserName = newTextField(238,25);
        tfPassword = newTextField(233,25);
        panel.add(new JLabel(" 用户名："));
        panel.add(tfUserName);
        panel.add(new JLabel(" 密码："));
        panel.add(tfPassword);
        return panel;
    }
    
    public JPanel getDialectPanel(){
        JPanel panel = newPanel(32);
        
        cbbDialect = new JComboBox();
        cbbDialect.addItem("oracle");
        cbbDialect.addItem("mysql");
        cbbDialect.addItem("postgresql");
        cbbDialect.addItem("other");
        tfDriverClass  = new TextField("oracle.jdbc.driver.OracleDriver");
        tfDriverClass.setMaximumSize(new Dimension(415,25));
        cbbDialect.setMaximumSize(new Dimension(110,25));
        panel.add(new JLabel(" 方言："));
        panel.add(cbbDialect);
        panel.add(tfDriverClass);
        
        cbbDialect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String selected = (String)cbbDialect.getSelectedItem();  
                if("oracle".equalsIgnoreCase(selected)){
                    tfDriverClass.setText("oracle.jdbc.driver.OracleDriver");
                    tfConnURL.setText("jdbc:oracle:thin:@127.0.0.1:1521:库名");
                    tfQuerySql.setText("SELECT t.table_name FROM user_tables t");
                }else if("mysql".equalsIgnoreCase(selected)){
                    tfQuerySql.setText("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = DATABASE()");
                    tfDriverClass.setText("com.mysql.jdbc.Driver");
                    tfConnURL.setText("jdbc:mysql://127.0.0.1:3306/库名");
                }else if("postgresql".equalsIgnoreCase(selected)){
                    tfDriverClass.setText("org.postgresql.Driver");
                    tfConnURL.setText("jdbc:postgresql://127.0.0.1:5432/库名");
                    tfQuerySql.setText("select tablename from pg_tables where schemaname='public'");
                }else{
                    tfDriverClass.setText("");
                    tfConnURL.setText("");
                    tfQuerySql.setText("");
                }
                cbbDialect.updateUI();
            }
        });
             
        return panel;
    }
    
    public JPanel getByExamplePanel1(){
        JPanel panel = newPanel(32);
        cbCountByExample = new JCheckBox("CountByExample", false);
        cbCountByExample.setMaximumSize(new Dimension(150,25));
        cbDeleteByExample = new JCheckBox("DeleteByExample", false);
        cbDeleteByExample.setMaximumSize(new Dimension(150,25));
        cbExampleQueryId = new JCheckBox("ExampleQueryId", false);
        cbExampleQueryId.setMaximumSize(new Dimension(150,25));

        panel.add(cbCountByExample);
        panel.add(cbDeleteByExample);
        panel.add(cbExampleQueryId);
        return panel;
    }
    public JPanel getByExamplePanel2(){
        JPanel panel = newPanel(32);
        cbUpdateByExample = new JCheckBox("UpdateByExample", false);
        cbUpdateByExample.setMaximumSize(new Dimension(150,25));
        cbSelectByExample = new JCheckBox("SelectByExample", false);
        cbSelectByExample.setMaximumSize(new Dimension(150,25));
        cbOverwrite  = new JCheckBox("Overwrite", false);
        cbOverwrite.setMaximumSize(new Dimension(120,25));
        cbOverwrite.setBackground(Color.CYAN);
        panel.add(cbUpdateByExample);
        panel.add(cbSelectByExample);
        panel.add(cbOverwrite);
        return panel;
    }
    
    public JPanel getModelPackPanel(){
        JPanel panel = newPanel(32);
        tfModelPack = newTextField(488,25);
        panel.add(new JLabel(" Model包名："));
        panel.add(tfModelPack);
        return panel;
    }
    
    public JPanel getDaoPackPanel(){
        JPanel panel = newPanel(32);
        tfDaoPack = newTextField(495,25);
        panel.add(new JLabel("   Dao包名："));
        panel.add(tfDaoPack);
        return panel;
    }
    
    public JPanel getConnectionURLPanel(){
        JPanel panel = newPanel(32);
        tfConnURL = newTextField(496,25);
        panel.add(new JLabel(" 连接地址： "));
        panel.add(tfConnURL);
        
        return panel;
    }
    
    
    public JPanel getSqlMapPanel(){
        JPanel panel = newPanel(32);
        tfMapPack = newTextField(490, 25);
        panel.add(new JLabel(" SqlMap目录:"));
        panel.add(tfMapPack);
        return panel;
    }
    
    public JPanel getQuerySqlPanel(){
        JPanel panel = newPanel(32);
        tfQuerySql = newTextField(510, 25);
        panel.add(new JLabel(" 查表SQL:"));
        panel.add(tfQuerySql);
        return panel;
    }
    
    
    public void queryDbTableNameAddToTable(){
        GeneratorConfiguration cfg = createConfig();
        if(!checkConfig(cfg)){
            return;
        }
        String driver = cfg.getDriverClass();
        String url = cfg.getConnectionURL();
        String sql = tfQuerySql.getText();
        String user = cfg.getUserName();
        String psw = cfg.getPassword();
        try {
            List<String> list = CyUtil.getTableList(cfg.getDriverPath(),driver, url, user, psw, sql);
            CheckTableModel tm = (CheckTableModel)table.getModel();
            int count = tm.getRowCount();
            for(int i = count-1; i >= 0; i--){
                tm.removeRow(i);
            }
            int k = 0;
            for(String tableName:list){
                tm.addRow(new Object[]{false,++k+"",tableName});
            }
            TableColumn column2 = table.getColumnModel().getColumn(2);
            column2.setPreferredWidth(getPreferredWidthForColumn(table,column2));
            table.setModel(tm);
            table.updateUI();
        } catch (Exception ex) {
            showMsgDialog("获取表名异常"+ex.getMessage());
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private static void showMsgDialog(String msg){
        JOptionPane.showMessageDialog(null,msg, "提示",JOptionPane.PLAIN_MESSAGE);
    }
    
    public boolean checkConfig(GeneratorConfiguration cfg){
        if(cfg.getDriverPath().isEmpty()){
            showMsgDialog("【数据库驱动路径】不能为空");
            return false;
        }
        if(cfg.getDistSrcDir().isEmpty()){
            showMsgDialog("【源代码保存路径】不能为空");
            return false;
        }
        if(cfg.getDriverClass().isEmpty()){
            showMsgDialog("【方言】不能为空");
            return false;
        }
        if(cfg.getConnectionURL().isEmpty()){
            showMsgDialog("【连接地址】不能为空");
            return false;
        }
        if(tfQuerySql.getText().isEmpty()){
            showMsgDialog("【查表SQL】不能为空");
            return false;
        }
        if(cfg.getUserName().isEmpty()){
            showMsgDialog("【用户名】不能为空");
            return false;
        }
        if(cfg.getPassword().isEmpty()){
            showMsgDialog("【密码】不能为空");
            return false;
        }if(cfg.getMapPack().isEmpty()){
            showMsgDialog("【SqlMap目录】不能为空");
            return false;
        }
        if(cfg.getModelPack().isEmpty()){
            showMsgDialog("【Model包名】不能为空");
            return false;
        }if(cfg.getDaoPack().isEmpty()){
            showMsgDialog("【Dao包名】不能为空");
            return false;
        }
        return true;
    }
    
    public GeneratorConfiguration createConfig(){
        GeneratorConfiguration cfg = new GeneratorConfiguration();
        cfg.setConnectionURL(tfConnURL.getText());
        cfg.setDaoPack(tfDaoPack.getText());
        cfg.setDistSrcDir(tfDistSrcPath.getText());
        cfg.setDriverClass(tfDriverClass.getText());
        cfg.setDriverPath(tfDriverPath.getText());
        cfg.setEnableCountByExample(cbCountByExample.isSelected()?"true":"false");
        cfg.setEnableDeleteByExample(cbDeleteByExample.isSelected()?"true":"false");
        cfg.setEnableSelectByExample(cbSelectByExample.isSelected()?"true":"false");
        cfg.setEnableUpdateByExample(cbUpdateByExample.isSelected()?"true":"false");
        cfg.setMapPack(tfMapPack.getText());
        cfg.setModelPack(tfModelPack.getText());
        cfg.setPassword(tfPassword.getText());
        cfg.setSelectByExampleQueryId(cbExampleQueryId.isSelected()?"true":"false");
        cfg.setUserName(tfUserName.getText());
        
        return cfg;
    }
    
    public void genCode(){
        try{
            List<String> warnings = new ArrayList<String>();
            final boolean overwrite = cbOverwrite.isSelected();
            List<String> list = getCheckTableNameList();
            GeneratorConfiguration cfg = createConfig();
            if (checkConfig(cfg)) {
                if(list.isEmpty()){
                    showMsgDialog("选择要生成代码的表名");
                    return;
                }
                cfg.setTableList(list);
                ConfigurationParser cp = new ConfigurationParser(warnings);
                InputStream is = cfg.parse();
                Configuration configuration = cp.parseConfiguration(is);
                DefaultShellCallback callback = new DefaultShellCallback(overwrite);
                final MyBatisGenerator mybatisGenerator = new MyBatisGenerator(configuration, callback, warnings);
                Thread gen = new Thread(){
                    @Override
                    public void run() {
                        try {
                            mybatisGenerator.generate(null);
                        } catch (Exception ex) {
                            
                        }
                    } 
                };
                
                Thread t = new Thread(){
                    @Override
                    public void run() {
                        int i = 1;
                        while(progress){
                            try {
                                int n = i%6;
                                String msg = "     代码生成中";
                                for(int k = 0; k < i; k++){
                                    msg += "。";
                                }
                                System.out.println(msg);
                                progressBar.setText(msg);
                                i++;
                                Thread.sleep(200);
                            } catch (Exception ex) {
                                
                            }
                        }
                    } 
                    
                };
                gen.start();
                t.start();
                gen.join();
                progress = false;
                progressBar.setText("     执行结束");
            }
        }catch(Exception e){
            CyUtil.writeLog(this.getClass(), e);
            showMsgDialog(e.getMessage());
        }
    }
    
    public JPanel getBtnPanel(){
        JPanel panel = newPanel(32);
        panel.add(Box.createRigidArea(new Dimension (150,60)));
        JButton qryTableNameBtn = new JButton("获取表名");
        qryTableNameBtn.setBackground(Color.YELLOW);
        qryTableNameBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                queryDbTableNameAddToTable();
            }
        });
       
        JButton genCodeBtn = new JButton("代码生成");
        genCodeBtn.setBackground(Color.GREEN);
        genCodeBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                genCode();
            }
        });
        
        progressBar =  new JLabel("     Hi");
        
        panel.add(qryTableNameBtn);
        panel.add(new JLabel("     "));
        panel.add(genCodeBtn);
        panel.add(progressBar);
        return panel;
    }
    
    public JPanel getTablePanel() {
        String[] columnNames = {"","序号", "表名"};
        table = new CheckTable();
        CheckTableModel tm = new CheckTableModel(columnNames);
        table.setModel(tm);
        table.setEnabled(true);
        // 设置标题带有复选框的列
        table.setCheckHeaderColumn(0);
        table.getColumnModel().getColumn(0).setPreferredWidth(28);
        table.getColumnModel().getColumn(1).setPreferredWidth(35);
        table.getColumnModel().getColumn(2).setPreferredWidth(170);
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.setAutoscrolls(true);
        table.setMinimumSize(new Dimension(160, 100));
        try {
            tm.addRow(new Object[]{false,"QQ","275951533"});
            tm.addRow(new Object[]{false,"藏言","beetle082@163.com"});
        } catch (Exception ex) {
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
        JScrollPane spane = new JScrollPane(table);
        //spane.setPreferredSize(new Dimension(250, spane.getHeight()));
        
        JPanel panel = new JPanel();
        BoxLayout layout = new BoxLayout(panel,BoxLayout.Y_AXIS);
        panel.setLayout(layout);
        panel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
        panel.setPreferredSize(new Dimension(250, spane.getHeight()));
        panel.add(spane);
        panel.add(getCopyRightPanel());
        return panel;
    }
    
    //[start]自动调列宽
    private int getPreferredWidthForColumn(JTable table,TableColumn col) {
        int hw = columnHeaderWidth(table,col);  // hw = header width
        int cw = widestCellInColumn(table,col);  // cw = column width
        return hw > cw ? hw : cw;

    }
    private int columnHeaderWidth(JTable table,TableColumn col) {
        TableCellRenderer renderer = table.getTableHeader().getDefaultRenderer();
        Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0);
        return comp.getPreferredSize().width;
    }
    private int widestCellInColumn(JTable table,TableColumn col) {
        int c = col.getModelIndex();
        int width, maxw = 0;
        for (int r = 0; r < table.getRowCount(); r++) {
            TableCellRenderer renderer = table.getCellRenderer(r, c);
            Component comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, c), false, false, r, c);
            width = comp.getPreferredSize().width;
            maxw = width > maxw ? width : maxw;
        }
        if(maxw<90)maxw = 90;
        return maxw + 10;
    }
    //[end]自动调列宽
    
    
    public List<String> getCheckTableNameList(){
       CheckTableModel tm = (CheckTableModel) table.getModel();
       int count = tm.getRowCount();
       if(count<=0){
           return null;
       }
       List<String> list = new ArrayList<String>();
       for(int i = 0; i<count;i++){
           Boolean cb = (Boolean)tm.getValueAt(i, 0);
           if(cb){
               list.add((String)tm.getValueAt(i, 2));
           }
       }
       //System.out.println(list);
       return list;
    }
    
    
}
